// @ts-nocheck
import { defineComponent, watch, markRaw } from "vue"
import { toCamelCase, deepClone, debounce } from "../utils/utils"
import $store from '@/stores/counter';
let store

var comList = [],
  ctx,
  id_conf = {}
var html2canvas
export default defineComponent({
  props: ['defaultOption'],
  data() {
    return {
      useless: [
        "carousel",
        "main",
        "body",
        "table",
        "form",
        "opper",
        "drop",
        "menu",
        "option",
        "v2",
        "step",
        "tab",
        "empty",
        "collectio",
        "elcol",
        "elrow"
      ],
      currentCom: null,
      isMoving: false,
      screenTop: 0,
      defaultComs: {},
    }
  },
  beforeMount() {
    import('html2canvas').then((plugin) => {
      html2canvas = plugin.default;
    });
  },
  async created() {
    ctx = this
    store = $store().state
    for (const [key, com] of Object.entries(window._customComponents)) {
      //   if (key.startsWith("El") && !!com?.setup) {
      let item = this.useless.find((e) => {
        if (key.toLowerCase().includes(e)) {
          return true
        }
      })
      if (!item) comList.push(com)
      //   }
    }
    ctx.defaultOption.components.forEach((e, i) => {
      if (e.comName && !ctx.defaultComs[i]) {
        ctx.defaultComs[i] = e
      }
    })
    //  await ctx.initDefaultOption()
  },
  methods: {
    async initDefaultOption() {

      //await http.get("getDefaultOption").then((res) => {
      let defaultComs = {}

      ctx.defaultOption.components.forEach((e, i) => {
        if (e.comName && !defaultComs[i]) {
          defaultComs[i] = e
        }
      })
      ctx.defaultComs = markRaw(defaultComs)
      // })
    },
    async createCanvasByDom(dom) {
      var domElement = dom //document.getElementById(domId);
      let canvas
      //var ctx = canvas.getContext('2d');
      await html2canvas(domElement).then(function (cvs) {
        // 将Canvas添加到DOM中
        document.body.appendChild(cvs);
        canvas = cvs
      });
      //var rect = domElement.getBoundingClientRect();
      // canvas.width = rect.width;
      // canvas.height = rect.height;
      canvas.style.top = 0
      canvas.style.left = 0
      canvas.style.position = 'absolute'
      // var img = new Image();
      // img.onload = function () {
      //   ctx.drawImage(img, rect.left, rect.top);
      // }
      // img.src = "data:image/svg+xml," + encodeURIComponent(new XMLSerializer().serializeToString(domElement));
      return canvas
    },
    getFlatJson(obj: object, evalKeys = true, newObj = {}) {
      Object.keys(obj).forEach((k) => {
        if (
          Object.prototype.toString.call(obj[k]) === "[object Object]" &&
          k !== "varys"
        ) {
          ctx.getFlatJson(obj[k], undefined, newObj)
        } else {
          newObj[k] = obj[k] ?? newObj[k]
        }
      })

      return newObj
    },
    getComs(conf: any, isflat = false, isChild = false) {
      let flatConf = isflat ? conf : ctx.getFlatJson(conf, false) ////可能含v-for 先不eval
      if (!flatConf) return
      if (Array.isArray(flatConf)) {
        return flatConf.map((e) => {
          /////varys???
          return ctx.getComs(e, true)
        })
      }
      let renderCom
      let comName = toCamelCase(conf.comName.trim())
      const com = window._customComponents[comName] ?? comName
      let bindProp = undefined
      // if (bindProp)
      const dragProp = isChild ? {} : {
        onMouseleave: ctx.leaveUnit,
        onMouseover: ctx.overUnit,
        style: 'display:flex;align-items:center',
        class: 'comContainer',
        title: conf.title ?? conf.describe ?? '',
        id: comName + "_" + Math.ceil(Math.random() * 10 ** 6) + "_comContainer"
      }
      !isChild && (id_conf[dragProp.id] = conf
      )
      let child = conf.childNode?.length
        ? conf.childNode.map((e: any) => ctx.getComs(e, undefined, true))
        : conf.domProps?.innerText ??
        conf.innerText ??
        conf.domProps?.contentText ??
        conf.contentText
      if (conf.formItemProps?.prop || conf.formItemProps?.label) {
        renderCom = <com {...flatConf}>{child}</com>

        let formItemCom
        //class={conf.formItemProps?.isRequired ? "is-required" : ''}
        formItemCom = (
          <ElFormItem
            {...ctx.getFlatJson(conf.formItemProps)}
            class={conf.formItemProps?.isRequired ? "is-required" : ""}
          >
            {renderCom}
          </ElFormItem>
        )
        return <div {...dragProp}>{formItemCom}</div>
      } else {
        renderCom = (
          <div {...dragProp}>
            <com {...flatConf}>{child}</com>
          </div>
        )

        return renderCom
      }
    },
    getUnitDom(e, loop = 0) {
      if (e?.attributes?.id?.value?.includes("_comContainer")) {
        return e
      } else {
        loop += 1
        if (loop > 5) return null
        if (!e?.parentNode) {
          return null
        }
        return this.getUnitDom(e.parentNode, loop)
      }
    },
    overUnit(e) {
      let item = (this.currentCom = this.getUnitDom(e.target))
      e.stopPropagation()
    },
    leaveUnit(e) {
      this.currentCom = null
      let item = this.getUnitDom(e.target)
      e.stopPropagation()
    },
    editCom(k) {
      store.curIndex = k
    },
    delCom(k) {
      store.curIndex = k
      store.deleteDefaultCom += 1
    },
    renderItem() {
      let list = []
      Object.entries(ctx.defaultComs).forEach(([key, com]) => {
        let prop

        if (JSON.stringify(com) !== '{}') {
          prop = deepClone(com)
        } else prop = ctx.getDefaultProp(com)

        if (!prop) return
        let item = null
        // const dragProp = {
        //   onMouseleave: ctx.leaveUnit,
        //   onMouseover: ctx.overUnit,
        //   id:
        //     (key || com.name) +
        //     "_" +
        //     Math.ceil(Math.random() * 10 ** 6) +
        //     "_comContainer"
        // }
        try {
          item = (
            <div style={
              "width:90%;align-items:center;display:flex;justify-content:space-around;padding:4px 5%; margin-bottom:10px;height:fit-content;" +
              (store.curIndex == key ? 'background:#c6c8d1a3' : '')
            }>

              {ctx.getComs(prop)}
              <div style={"display:flex;justify-content:space-around;align-items:center;min-width:80px"}>
                <span style={'padding:0 8px;font-size: 15px;  cursor: pointer;color: #80cece;'} {...{
                  onClick: () => {
                    ctx.editCom(key)
                  },
                  class: 'textPanel'
                }} >编辑</span>
                <span
                  {...{
                    onClick: () => {
                      ctx.delCom(key)
                    },
                    class: 'textPanel',
                    style: 'font-size: 15px;  cursor: pointer;color: #80cece;'
                  }}
                >删除</span>
              </div>
            </div>
          )
        } catch (error) {
          item = (
            <div style="max-widht:100%;margin-bottom:10px;max-height:200px">
              {com.name}
            </div>
          )
        }
        list.push(item)
      })
      return list
      // comList.map(com =>
      //     (<com style='max-widht:100%;margin-bottom:10px;max-height:200px'></com>))
    },
    getScrollLen: debounce((val) => {
      ctx.scrollTop = val.scrollTop
    }, 100),
    getDefaultProp(com) {
      let item = ctx.defaultOption.components.find((e) => {
        if (
          e.comName.replaceAll("-", "").toLowerCase() === com.name.toLowerCase()
        ) {
          return true
        }
      })
      item = deepClone(item)
      item && (item.style += ";max-widht:100%;max-height:200px;")
      item && (item.title = com.name.slice(2, 20))
      return item
    }
  },
  directives: {
    draggable: {
      mounted: function (el, binding, vnode) {
        el.style.cursor = "grab"
        const parent = el
        //parent.style['overflow-y']
        const getUnitDom = (e, loop = 0) => {
          return ctx.currentCom
        }
        el.onmousedown = async function (e) {
          el.style.cursor = "grabbing"
          let el1 = getUnitDom(e.target)
          if (!el1) return
          ctx.$emit("dragStart")
          ctx.isMoving = true
          el1.className += " isMoving"
          let { clientX: ox, clientY: oy } = e
          let canvas = await ctx.createCanvasByDom(el1)
          let oIndex = el1.style.zIndex
          // el1.style.zIndex = "99"
          canvas.style.zIndex = "99"
          canvas.style.cursor = "grabbing"
          el1.style.opacity = 0.25
          canvas.style.opacity = 0.85
          let curDom = null
          document.onmousemove = function (e) {
            //  if (curDom?.className) curDom.className = curDom.className.replaceAll('isHover')
            let { clientX: tx, clientY: ty } = e
            canvas.style.transform =
              "translate(" + tx + "px," + ty + "px)"
            // el1.style.transform =
            //   "translate(" + (tx - ox) + "px," + (ty - oy + (ctx.scrollTop ?? 0)) + "px)"
            // let { x: cx, y: cy } = el1.getBoundingClientRect()
            // curDom = document.elementFromPoint(cx, cy);
            // if (curDom?.className) curDom.className += ' isHover'
          }
          document.onmouseup = function (e) {
            el1.style.zIndex = oIndex
            // ctx.$emit('dragEnd', el1, e)
            let { x: cx, y: cy } = canvas.getBoundingClientRect()
            curDom = document.elementFromPoint(cx, cy)
            // el1.style.transform = "unset"
            // canvas.style.transform = "unset"
            // canvas.style.opacity = "unset"
            document.body.removeChild(canvas)
            el1.style.opacity = "unset"
            el.style.cursor = "grab"
            document.onmouseup = document.onmousemove = null
            ctx.isMoving = false
            el1.className = el1.className.replaceAll("isMoving", "")

            // setTimeout(function () {
            let comName = el1?.attributes?.id?.value
            if (!curDom) return

            if (!comName || !id_conf[comName]) return
            // comName = comName.split('_')[0]
            let conf = id_conf[comName]
            conf.parentId = comName
            ctx.$emit("dragEnd", conf, curDom, undefined, [cx, cy])

            // }, 100);
          }
        }
      },
      unmounted(el, binding, vnode) {
        el.onmousedown = null
      }
    }
  },
  watch: {
    defaultOption: {
      handler(nv) {
        ctx.initDefaultOption()

      },
      deep: true,
    }
  },
  render(ctx) {
    // return <div>111</div>
    return (
      <div
        style={
          "display:flex;flex-direction:column;max-height:660px;position:relative"
        }
        v-draggable
      >
        <el-scrollbar {...{
          onScroll: (val) => {
            ctx.getScrollLen(val)
          }
        }}>
          {ctx.renderItem()}
        </el-scrollbar>
      </div>
    )
  }
})
